
Ext.namespace("Addama.groups");

Addama.groups.GroupAdmin = function() {

    // private variables
    new Ext.data.JsonStore({
        storeId: "groups",
        url: "/addama-groups/groups",
        root: "groups",
        fields: ["name", "uri"],
        sortInfo: {
            field: "name",
            direction: "ASC"
        }
    });

    new Ext.data.JsonStore({
        storeId: "allUsers",
        url: "/addama-users/users",
        root: "users",
        fields: ["firstName", "lastName", "emailAddress", "uri"],
        sortInfo: {
            field: "lastName",
            direction: "ASC"
        }
    });

    var membersDS = new Ext.data.Store({
        storeId: "members",
        data: [],
        reader: new Ext.data.ArrayReader([], [ {name: "name"} ])
    });

    var membersMap = {};

    // private functions
    function onGroupSelect() {
        Ext.getCmp("deleteGroupButton").enable();
        updateGroup();
    }

    function updateGroup() {
        var gname = getSelectedGroupName();
        if (!gname) return;
        
        Ext.Ajax.request({
            url: "/addama-groups/groups/" + gname,
            method: "get",
            success: function(o) {
                var json = Ext.decode(o.responseText);
                if (json) {
                    Ext.getCmp("groupNameLabel").setValue(json.name);
                    Ext.getCmp("groupDescField").setValue(json.description);
                    Ext.getCmp("groupCreatedOnLabel").setValue(json.created_on);
//                    Ext.getCmp("groupNumberOfMembers").setValue(json.numberOfMembers);
                    updateMembers(json);
                }
            }
        });
    }

    function updateMembers(json) {
        var groupName = json.name;
        var numberOfMembers = json.numberOfMembers;
        var membersDS;
        membersMap = {};
        if (numberOfMembers && numberOfMembers > 0) {
            membersDS = new Ext.data.JsonStore({
                storeId: "members",
                url: "/addama-groups/groups/" + groupName,
                root: "members",
                fields: ["name", "uri"],
                sortInfo: {
                    field: "name",
                    direction: "ASC"
                }
            });
            membersDS.load({
                callback: function() {
                    membersDS.each(function(r) {
                        membersMap[r.data.name] = true;
                    });
                    updateMembersGrid();
                }
            });
        }
        else {
            membersDS = new Ext.data.Store({
                storeId: "members",
                data: [],
                reader: new Ext.data.ArrayReader([], [ {name: "name"} ])
            });
            updateMembersGrid();
        }
    }

    function updateMembersGrid() {
        var grid = Ext.getCmp("membersGrid");
        var ds = Ext.StoreMgr.lookup("members");
        grid.reconfigure(ds, grid.getColumnModel());
    }

    function onAddGroup(button) {
        var win = new Ext.Window({
            title: "Add Group",
            closable: false,
            modal: true,
            width: 300,
            autoHeight: true,
            items: [
                new Ext.FormPanel({
                    autoHeight: true,
                    autoWidth: true,
                    border: false,
                    items: [
                        new Ext.form.FieldSet({
                            defaultType: "textfield",
                            autoHeight: true,
                            autoWidth: true,
                            border: false,
                            items: [{
                                id: "addGroupNameField",
                                fieldLabel: "Name",
                                name: "name",
                                allowBlank: false
                            },{
                                id: "addGroupDescField",
                                fieldLabel: "Description",
                                name: "name"
                            }],
                            buttons: [{
                                text: "Add",
                                handler: function() {
                                    if (Ext.getCmp("addGroupNameField").getValue() !== "") {
                                        addGroupByForm();
                                        win.close();
                                    }
                                }
                            },{
                                text: "Cancel",
                                handler: function() {
                                    win.close();
                                }
                            }]
                        })
                    ]
                })
            ]
        });
        win.show(button);
    }

    function onDeleteGroup() {
        if (!getSelectedGroupName()) return;
        Addama.groups.GroupAdmin.deleteGroup(getSelectedGroupName(), 
            function() {
            Ext.getCmp("deleteGroupButton").disable();
            updateGroups();
        });
    }

    function addGroupByForm() {
        var groupName = Ext.getCmp("addGroupNameField").getValue();
        var groupDesc = Ext.getCmp("addGroupDescField").getValue();
        Addama.groups.GroupAdmin.addGroup(groupName, groupDesc, function() {
            updateGroups();
        });
    }

    function updateGroups() {
        Ext.StoreMgr.lookup("groups").load({
            callback: function() {
                var groupsGrid = Ext.getCmp("groupsGrid");
                groupsGrid.reconfigure(Ext.StoreMgr.lookup("groups"), groupsGrid.getColumnModel());
            }
        });
    }

    function onAddMembers(button) {
        Ext.StoreMgr.lookup("allUsers").load({
            callback: function() {
                Ext.StoreMgr.lookup("allUsers").filterBy(function(r) {
                    return (!membersMap[r.data.emailAddress]);
                });
            }
        });
        var win = new Ext.Window({
            title: "Add Member(s)",
            closable: false,
            modal: true,
            width: 400,
            autoHeight: true,
            items: [
                new Ext.form.FormPanel({
                    items: [
                        new Ext.grid.GridPanel({
                            id: "addMembersGrid",
                            store: Ext.StoreMgr.lookup("allUsers"),
                            columns: [{
                                id: "lastName",
                                header: "Last name",
                                sortable: true,
                                dataIndex: "lastName"
                            },{
                                id: "firstName",
                                header: "First name",
                                sortable: true,
                                dataIndex: "firstName"
                            },{
                                id: "emailAddress",
                                header: "Email",
                                sortable: true,
                                dataIndex: "emailAddress"
                            }],
                            viewConfig: {
                                forceFit: true
                            },
                            sm: new Ext.grid.RowSelectionModel(),
                            height: 300
                        })
                    ],
                    buttons: [{
                        text: "Add",
                        handler: function() {
                            addMembersByForm();
                            win.close();
                        }
                    },{
                        text: "Cancel",
                        handler: function() {
                            win.close();
                        }
                    }]
                })
            ]
        });
        win.show(button);
    }

    function addMembersByForm() {
        var grid = Ext.getCmp("addMembersGrid");
        var records = grid.getSelectionModel().getSelections();
        var gname = getSelectedGroupName();
        if (!gname) return;
        Addama.groups.GroupAdmin.addMembers(gname, records, function() {
            updateGroup();
        });
    }

    function onRemoveMembers() {
        var grid = Ext.getCmp("membersGrid");
        var records = grid.getSelectionModel().getSelections();
        var gname = getSelectedGroupName();
        if (!gname) return;
        for (i = 0; i < records.length; i++) {
            var username = records[i].data.name;
            Addama.groups.GroupAdmin.removeMember(gname, username, function() {
                if (i < records.length) return;
                Ext.getCmp("removeMembersButton").disable();
                updateGroup();
            });
        }
    }

    function onSaveGroupProperties() {
        var gname = getSelectedGroupName();
        if (!gname) return;
        var desc = Ext.getCmp("groupDescField").getValue();
        Addama.groups.GroupAdmin.saveGroupProperties(gname, desc, function() {
            Ext.getCmp("saveGroupPropertiesButton").disable();
        });
    }

    function onChangeGroupDetails() {
        Ext.getCmp("saveGroupPropertiesButton").enable();
    }

    function onMemberSelect() {
        Ext.getCmp("removeMembersButton").enable();
    }

    function getSelectedGroupName() {
        var g = Ext.getCmp("groupsGrid");
        if (g.getSelectionModel().getSelected()) {
            return g.getSelectionModel().getSelected().data.name;
        }
        return undefined;
    }


    // public
    return {
        // public properties

        // public methods
        deleteGroup: function(groupName, callOnSuccess) {
            Ext.Ajax.request({
                url: "/addama-groups/groups/" + groupName + "/delete",
                method: "post", // TODO : delete
                success: callOnSuccess,
                failure: function() {
                    Ext.MessageBox.show({
                        title: "Error",
                        msg: "An error occurred while deleting group '" + groupName + "'.",
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.ERROR
                    });
                }
            });
        },

        addGroup: function(groupName, groupDesc, callOnSuccess) {
            Ext.Ajax.request({
                url: "/addama-groups/groups/" + groupName + "/create",
                method: "post",
                params: {
                    JSON: Ext.encode({ description: groupDesc || "No description" })
                },
                success: callOnSuccess,
                on409: function() {
                    Ext.MessageBox.show({
                        title: "Group Exists",
                        msg: "Group with name '" + groupName + "' already exists.",
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.ERROR
                    });
                },
                failure: function(o) {
                   if (o.status == 409) {
                        Ext.MessageBox.show({
                            title: "Group Exists",
                            msg: "Group with name '" + groupName + "' already exists.",
                            buttons: Ext.MessageBox.OK,
                            icon: Ext.MessageBox.ERROR
                        });
                    }
                    else {
                        Ext.MessageBox.show({
                            title: "Error",
                            msg: "An error occurred while adding group '" + groupName + "'.",
                            buttons: Ext.MessageBox.OK,
                            icon: Ext.MessageBox.ERROR
                        });
                    }
                }
            });
        },

        addMember: function(groupName, username, callOnSuccess) {
            var json = {};
            json[username] = "/addama-users/users/" + username;

            Ext.Ajax.request({
                url: "/addama-groups/groups/" + groupName,
                method: "post",
                params: {
                    JSON: Ext.encode({"members": json})
                },
                success: callOnSuccess,
                failure: function() {
                    Ext.MessageBox.show({
                        title: "Error",
                        msg: "An error occurred while adding user '" + username + "' to group '" + groupName + "'.",
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.ERROR
                    });
                }
            });
        },

        addMembers: function(groupName, records, callOnSuccess) {
            var json = {};
            for (var i = 0; i < records.length; i++) {
                json[records[i].json.fullName] = "/addama-users/users/" + records[i].data.emailAddress;
            }

            Ext.Ajax.request({
                url: "/addama-groups/groups/" + groupName,
                method: "post",
                params: {
                    JSON: Ext.encode({"members":json})
                },
                success: callOnSuccess,
                failure: function() {
                    Ext.MessageBox.show({
                        title: "Error",
                        msg: "An error occurred while adding members to group '" + groupName + "'.",
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.ERROR
                    });
                }
            });
        },

        removeMember: function(groupName, username, callOnSuccess) {
            var json = {};
            json[username] = "null";
            
            Ext.Ajax.request({
                url: "/addama-groups/groups/" + groupName,
                method: "post",
                params: {
                    JSON: Ext.encode({"members":json})
                },
                success: callOnSuccess,
                failure: function() {
                    Ext.MessageBox.show({
                        title: "Error",
                        msg: "An error occurred while removing user '" + username + "' from group '" + groupName + "'.",
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.ERROR
                    });
                }
            });
        },

        saveGroupProperties: function(groupName, groupDesc, callOnSuccess) {
            Ext.Ajax.request({
                url: "/addama-groups/groups/" + groupName,
                method: "post",
                params: {
                    JSON: Ext.encode({ "description": groupDesc })
                },
                success: callOnSuccess,
                failure: function() {
                    Ext.MessageBox.show({
                        title: "Error",
                        msg: "An error occured while saving properties for group '" + groupName + "'.",
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.ERROR
                    });
                }
            });
        },

        loadGroups: function() {
            var groupsGrid = new Ext.grid.GridPanel({
                id: "groupsGrid",
                store: Ext.StoreMgr.lookup("groups"),
                columns: [
                   { id: "name", header: "Name", sortable: true, dataIndex: "name" }
                ],
                viewConfig: {
                    forceFit: true
                },
                sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
                stripeRows: true,
                autoHeight: true,
                border: false,
                hideHeaders: true,
                listeners: {
                    rowclick: onGroupSelect
                }
            });

            var membersGrid = new Ext.grid.GridPanel({
                id: "membersGrid",
                title: "Group Members",
                store: membersDS,
                columns: [{
                    id: "name",
                    header: "User ID",
                    sortable: true,
                    dataIndex: "name"
                }],
                viewConfig: {
                    forceFit: true
                },
                sm: new Ext.grid.RowSelectionModel(),
                stripeRows: true,
                autoHeight: true,
                hideHeaders: true,
                border: false,
                tbar: [
                    new Ext.Button({
                        text: "Add member(s)",
                        handler: onAddMembers
                    }),
                    new Ext.Button({
                        id: "removeMembersButton",
                        text: "Remove member(s)",
                        disabled: true,
                        handler: onRemoveMembers
                    })
                ],
                listeners: {
                    rowclick: onMemberSelect
                }
            });

            var groupDetailsForm = new Ext.form.FormPanel({
                id: "groupDetailsForm",
                title: "Group Properties",
                border: false,
                items: [
                    new Ext.form.FieldSet({
                        autoHeight: true,
                        autoWidth: true,
                        border: false,
                        items: [
                            new Ext.form.TextField({
                                id: "groupNameLabel",
                                fieldLabel: "Name",
                                name: "name",
                                readOnly: true,
                                style: "background: transparent;border: none;"
                            }),
                            new Ext.form.TextField({
                                id: "groupCreatedOnLabel",
                                fieldLabel: "Created on",
                                name: "created_on",
                                readOnly: true,
                                style: "background: transparent;border: none;"
                            }),
                            new Ext.form.TextField({
                                id: "groupDescField",
                                fieldLabel: "Description",
                                name: "description",
                                listeners: {
                                    focus: onChangeGroupDetails
                                }
                            })
                        ]
                    })
                ],
                buttons: [{
                    id: "saveGroupPropertiesButton",
                    text: "Save",
                    disabled: true,
                    buttonAlign: 'left',                                                                    
                    handler: onSaveGroupProperties
                }]
            });

            new Ext.Panel({
                width: 800,
                height: 600,
                border: false,
                renderTo: "content-groups",
                layout: "border",
                items: [
                {
                    region: "west",
                    title: "Groups",
                    width: 200,
                    split: true,
                    items: [
                        groupsGrid
                    ],
                    tbar: [
                        new Ext.Button({
                            text: "Add group",
                            listeners: {
                                click: onAddGroup
                            }
                        }),
                        new Ext.Button({
                            id: "deleteGroupButton",
                            text: "Delete group",
                            disabled: true,
                            listeners: {
                                click: onDeleteGroup
                            }
                        })
                    ]
                },{
                    id: "editGroupPanel",
                    region: "center",
                    split: true,
                    items: [
                        groupDetailsForm,
                        membersGrid
                    ]
                }]
            });

            Ext.StoreMgr.lookup("groups").load();
        },

        init: function() {
            Ext.Ajax.request({
                url: "/addama-rest/primary-repo/path/groups/create",
                method: "post",
                success: Addama.groups.GroupAdmin.loadGroups,
                failure: Addama.groups.GroupAdmin.loadGroups
            });
        }
    };
}();
